/*
 * @Author: Colin Dai
 * @Date: 2022-05-10 18:08:03
 * @LastEditors: Colin Dai
 * @LastEditTime: 2022-05-10 18:23:02
 * @FilePath: /jy-uos/src/softbus/communication/udp/source/udp_socket.c
 * @Description: UDP通信实现
 * dailianzheng@163.com
 * Copyright (c) 2022 by Colin.Dai, All Rights Reserved. 
 */
#include "udp_socket.h"
#include "nstackx_error.h"
#include "securec.h"
#include "os_adapter.h"
#include "log.h"


/**
 * @brief 创建UDP socket server
 * @param {sockaddr_in} *sockAddr
 * @return {*}
 */
int CreateUdpServer(const struct sockaddr_in *sockAddr)
{
    if (sockAddr == NULL) {
        return NSTACKX_EINVAL;
    }

    struct sockaddr_in localAddr;
    socklen_t len = sizeof(localAddr);
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        return NSTACKX_OVERFLOW;
    }

    (void)memset_s(&localAddr, sizeof(localAddr), 0, sizeof(localAddr));
    localAddr.sin_family = AF_INET;
    localAddr.sin_port = sockAddr->sin_port;

    
    if (sockAddr->sin_addr.s_addr != 0) {
        localAddr.sin_addr.s_addr = sockAddr->sin_addr.s_addr;
    } else {    
        localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
       
    }

    if (bind(sockfd, (struct sockaddr *)&localAddr, len) == -1) {
        CloseSocket(&sockfd);
        return NSTACKX_EFAILED;
    }

    if (getsockname(sockfd, (struct sockaddr *)&localAddr, &len) == -1) {
        CloseSocket(&sockfd);
        return NSTACKX_EFAILED;
    }
    return sockfd;
}

/**
 * @brief 创建UDP客户端
 * @param {sockaddr_in} *sockAddr
 * @return {*}
 */
int CreateUdpClient(const struct sockaddr_in *sockAddr)
{
    if (sockAddr == NULL) {
        return NSTACKX_EFAILED;
    }

    struct sockaddr_in tmpAddr;
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        return NSTACKX_EFAILED;
    }

    int ret = connect(sockfd, (struct sockaddr *)sockAddr, sizeof(struct sockaddr));
    if (ret != 0) {
        CloseSocket(&sockfd);
        return NSTACKX_EFAILED;
    }

    socklen_t srcAddrLen = sizeof(struct sockaddr_in);
    (void)memset_s(&tmpAddr, sizeof(tmpAddr), 0, sizeof(tmpAddr));
    ret = getsockname(sockfd, (struct sockaddr *)&tmpAddr, &srcAddrLen);
    if (ret != 0) {
        CloseSocket(&sockfd);
        return NSTACKX_EFAILED;
    }

    return sockfd;
}

/**
 * @brief 发送UDP信息
 * @param {SocketInfo} *socket
 * @param {uint8_t} *buffer
 * @param {size_t} length
 * @return {*}
 */
int UdpSocketSend(const SocketInfo *socket, const uint8_t *buffer, size_t length)
{
    if (buffer == NULL || socket == NULL) {
        return NSTACKX_EFAILED;
    }

    socklen_t dstAddrLen = sizeof(struct sockaddr_in);
    int ret = sendto(socket->cliendFd, buffer, length, 0, (struct sockaddr *)&socket->dstAddr, dstAddrLen);
    return ret;
}

/**
 * @brief 接收UDP信息
 * @param {int} socketFd
 * @param {uint8_t} *buffer
 * @param {size_t} length
 * @return {*}
 */
int UdpSocketRecv(int socketFd, uint8_t *buffer, size_t length)
{
    if (buffer == NULL || socketFd < 0) {
        return NSTACKX_EFAILED;
    }

    struct sockaddr_in addr;
    socklen_t len = sizeof(struct sockaddr_in);
    (void)memset_s(&addr, sizeof(addr), 0, sizeof(addr));
    int ret = recvfrom(socketFd, buffer, length, 0, (struct sockaddr *)&addr, &len);
    return ret;
}

